home *** CD-ROM | disk | FTP | other *** search
/ Night Owl 6 / Night Owl's Shareware - PDSI-006 - Night Owl Corp (1990).iso / 039a / mawk.zip / SPLIT.C < prev    next >
C/C++ Source or Header  |  1991-04-07  |  4KB  |  175 lines

  1.  
  2. /********************************************
  3. split.c
  4. copyright 1991, Michael D. Brennan
  5.  
  6. This is a source file for mawk, an implementation of
  7. the Awk programming language as defined in
  8. Aho, Kernighan and Weinberger, The AWK Programming Language,
  9. Addison-Wesley, 1988.
  10.  
  11. See the accompaning file, LIMITATIONS, for restrictions
  12. regarding modification and redistribution of this
  13. program in source or binary form.
  14. ********************************************/
  15.  
  16. /* $Log:    split.c,v $
  17.  * Revision 2.1  91/04/08  08:24:11  brennan
  18.  * VERSION 0.97
  19.  * 
  20. */
  21.  
  22. /* split.c */
  23.  
  24. #include "mawk.h"
  25. #include "symtype.h"
  26. #include "bi_vars.h"
  27. #include "bi_funct.h"
  28. #include "memory.h"
  29. #include "scan.h"
  30. #include "regexp.h"
  31. #include "field.h"
  32. #include <string.h>
  33.  
  34.  
  35. /* split string s on SPACE without changing s.
  36.    load the pieces into STRINGS and ptrs into
  37.    temp_buff.ptr_buff[] 
  38.    return the number of pieces */
  39.  
  40. int space_split( s )  
  41.   register char *s ;
  42. { char *back = strchr(s,0) ;
  43.   int i = 0 ;
  44.   int len ;
  45.   char *q ;
  46.   STRING  *sval ;
  47.  
  48.   while ( 1 )
  49.   { while ( scan_code[*(unsigned char*)s] == SC_SPACE )  s++ ;
  50.     if ( *s == 0 )  break ;
  51.     /* mark the front with q */
  52.     q = s++ ;
  53.     *back = ' ' ; /* sentinal */
  54.     while ( scan_code[*(unsigned char*)s] != SC_SPACE )  s++ ;
  55.     *back = 0 ;
  56.     sval = (STRING *) (temp_buff.ptr_buff[i++] = 
  57.          (PTR) new_STRING((char *) 0, len = s - q )) ;
  58.     (void) memcpy(sval->str, q, len) ;
  59.   }
  60.   if ( i > MAX_FIELD ) 
  61.      rt_overflow("maximum number of fields", MAX_FIELD) ;
  62.   return i ;
  63. }
  64.  
  65.  
  66. char *re_pos_match(s, re, lenp)
  67.   register char *s ; 
  68.   PTR re ; unsigned *lenp ;
  69. {
  70.   while ( s = REmatch(s, re, lenp) )
  71.         if ( *lenp )   return s ;
  72.         else
  73.         if ( *s == 0 )  break ;
  74.         else s++ ;
  75.  
  76.   return (char *) 0 ;
  77. }
  78.  
  79. int re_split(s, re)
  80.   char *s ;
  81.   PTR  re ;
  82. { register char *t ;
  83.   int i = 0 ;
  84.   unsigned mlen, len ;
  85.   STRING *sval ;
  86.  
  87.   while ( t = re_pos_match(s, re, &mlen) )
  88.   { sval = (STRING*)(temp_buff.ptr_buff[i++] = (PTR)
  89.             new_STRING( (char *)0, len = t-s) ) ;
  90.     (void) memcpy(sval->str, s, len) ;
  91.     s = t + mlen ;
  92.   }
  93.   temp_buff.ptr_buff[i++] = (PTR) new_STRING(s) ;
  94.   if ( i > MAX_FIELD ) 
  95.      rt_overflow("maximum number of fields", MAX_FIELD) ;
  96.   return i ;
  97. }
  98.     
  99. /*  split(s, X, r)
  100.     split s into array X on r
  101.  
  102.     entry: sp[0] holds r
  103.            sp[-1] pts at X
  104.            sp[-2] holds s
  105. */
  106. CELL *bi_split(sp)
  107.   register CELL *sp ;
  108.   int cnt ;   /* the number of pieces */
  109.   double dcnt ; /* double version of cnt */
  110.   ARRAY A ;
  111.   CELL  *cp ;
  112.   char *ofmt ;
  113.  
  114.  
  115.   if ( sp->type < C_RE )  cast_for_split(sp) ;
  116.         /* can be C_RE, C_SPACE or C_SNULL */
  117.   sp -= 2 ;
  118.   if ( sp->type < C_STRING )  cast1_to_s(sp) ;
  119.  
  120.   if ( string(sp)->len == 0 ) /* nothing to split */
  121.   { free_STRING( string(sp) ) ;
  122.     sp->type = C_DOUBLE ; sp->dval = 0.0 ;
  123.     return sp ;
  124.   }
  125.  
  126.   switch ( (sp+2)->type )
  127.   {
  128.     case C_RE :
  129.         cnt = re_split(string(sp)->str, (sp+2)->ptr) ;
  130.         break ;
  131.  
  132.     case C_SPACE :
  133.         cnt = space_split(string(sp)->str) ;
  134.         break ;
  135.  
  136.     /* this case could be done by C_RE, but very slowly.
  137.        Since it is the common way to eliminate fields,
  138.        we'll treat the special case for speed */
  139.     case C_SNULL : /* split on empty string */
  140.         cnt = 1 ;
  141.         temp_buff.ptr_buff[0] = sp->ptr ;
  142.         string(sp)->ref_cnt++ ;
  143.         break ;
  144.  
  145.     default : bozo("bad splitting cell in bi_split") ;
  146.   }
  147.  
  148.   /* now load the array */
  149.  
  150.   free_STRING( string(sp) ) ;
  151.  
  152.   sp->type = C_DOUBLE ;
  153.   sp->dval = dcnt = (double) cnt ;
  154.  
  155.   ofmt = string(field + OFMT)->str ;
  156.   A = (ARRAY) (sp+1)->ptr  ;
  157.  
  158.   while ( cnt )
  159.   { char xbuff[256] ;
  160.     /* this big in case the user did something goofy with
  161.        OFMT  */
  162.   
  163.     (void) sprintf(xbuff, ofmt, dcnt ) ;
  164.     dcnt -= 1.0 ;
  165.     cp = array_find( A, xbuff, 1) ;
  166.     cell_destroy(cp) ;
  167.     cp->ptr = temp_buff.ptr_buff[--cnt] ;
  168.     cp->type = C_MBSTRN ;
  169.   }
  170.  
  171.   return sp ;
  172. }
  173.  
  174.